package com.aricwang.easyprofile.profile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.AudioManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SimpleAdapter;
import android.widget.ToggleButton;

import com.aricwang.easyprofile.R;
import com.aricwang.easyprofile.service.ProfileService;

public class ProfileActivity extends ListActivity {
	private static final int DIALOG_WARNING 		= 1;
	private static final int DIALOG_PROFILE_NAME 	= 2;
	private static final int DIALOG_VOLUME 			= 3;
	private static final int DIALOG_VIBRATE 		= 4;
	private static final int DIALOG_WIRELESS 		= 5;
	private static final int DIALOG_DISPLAY 		= 6;
	
	public static final int TIMEOUT_NOCHANGE	= Profile.NOCHANGE;
	public static final int TIMEOUT_30S			= 30;
	public static final int TIMEOUT_1M 			= 60;
	public static final int TIMEOUT_2M 			= 120;
	public static final int TIMEOUT_5M 			= 300;
	public static final int TIMEOUT_10M 		= 600;
	public static final int TIMEOUT_NEVER		= 0;
	
	private SimpleAdapter mAdapter = null;
	
	private int mRequest;
	private String mWarning = new String();

	// profile 
	private Profile mProfile;

	/////////////////////////////////////////////////////////////////////////////////////////
	// Static functions 
	/////////////////////////////////////////////////////////////////////////////////////////

	static void startActivity(Activity activity, int request, int profileId, String profileName) {
		Intent intent = new Intent().setClass(activity, ProfileActivity.class);
		intent.putExtra("Request", request);
		intent.putExtra("ProfileId", profileId);
		intent.putExtra("ProfileName", profileName);
		activity.startActivityForResult(intent, request);
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////
	// Public functions 
	/////////////////////////////////////////////////////////////////////////////////////////

	// set the warning string which will be shown by warning dialog
	public void setWarning(int stringId) {
		mWarning = getString(stringId);
	}
	
	// update the ListAdapter with the current data
	public void updateListAdapter() {
		String[] from = new String[]{"title", "info", "more"};
        int to[] = new int[]{R.id.title, R.id.info, R.id.more};
        mAdapter = new SimpleAdapter(this, getData(), 
        		R.layout.profile_details_row, from, to);
		
        setListAdapter(mAdapter);
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////
	// Override functions 
	/////////////////////////////////////////////////////////////////////////////////////////
	
	protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        initMembers();
        setContentView(R.layout.list_details);
		updateListAdapter();
    }
	
	protected void onListItemClick(ListView l, View v, int position, long id) {
		switch(position) {
		case 0:		// profile name edit
			showDialog(DIALOG_PROFILE_NAME);
			break;
		case 1:		// volume
			showDialog(DIALOG_VOLUME);
			break;
		case 2:
			showDialog(DIALOG_VIBRATE);
			break;
		case 3:
			showDialog(DIALOG_WIRELESS);
			break;
		case 4:
			showDialog(DIALOG_DISPLAY);
			break;
		default:
			break;
		}
		
		mAdapter.notifyDataSetChanged();
	}
		
	protected Dialog onCreateDialog(int id) {
	    Dialog dialog = null;
        switch(id) {
	    case DIALOG_WARNING:
	    	dialog = createDialogWarning();
	    	break;
	    	
	    case DIALOG_PROFILE_NAME:
            dialog = createDialogProfileName();	
	        break;
	        
	    case DIALOG_VOLUME:
	    	dialog = createDialogVolume();
	    	break;
	        
	    case DIALOG_VIBRATE:
	    	dialog = createDialogVibrate();
	    	break;

	    case DIALOG_WIRELESS:
	    	dialog = createDialogWireless();
	    	break;

	    case DIALOG_DISPLAY:
	    	dialog = createDialogDisplay();
	    	break;

	    default:
	    	break;
	    }
	    
	    return dialog;
	}

	protected void onPrepareDialog(int id, Dialog dialog) {
	    switch(id) {
	    default:
	    	break;
	    }
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////
	// OnClickListener interface implementation
	// handle the click event of the buttons on this page: save and cancel
	/////////////////////////////////////////////////////////////////////////////////////////
	public void onClick(View v) {
		int id = v.getId();
		
		switch(id) {
		case R.id.btn_save:
//			Toast.makeText(this, "Save clicked", Toast.LENGTH_SHORT).show();
			saveProfile();
			ProfileService.notifyConfigChanged(this);
			setResult(RESULT_OK);
			break;
		case R.id.btn_cancel:
//			Toast.makeText(this, "Cancel clicked", Toast.LENGTH_SHORT).show();
			setResult(RESULT_CANCELED);
			break;
		default:
			break;
		}
		
		finish();
	}
	
	//////////////////////////////////////////////////////////////////////////////////////////////
	// Private functions
	//////////////////////////////////////////////////////////////////////////////////////////////
	
	// init the members on create
	private void initMembers() {
    	mRequest = ProfileListActivity.REQ_ADD_PROFILE;
        
        Intent intent = getIntent();
        if (intent == null || intent.getExtras() == null) {
        	return;
        }
        
    	mRequest = intent.getExtras().getInt("Request");

    	switch(mRequest) {
        case ProfileListActivity.REQ_ADD_PROFILE:
        	mProfile = new Profile();
        	mProfile.mProfileName = intent.getExtras().getString("ProfileName");
        	break;
       
        case ProfileListActivity.REQ_EDIT_PROFILE:
        case ProfileListActivity.REQ_COPY_PROFILE:
        	int id = intent.getExtras().getInt("ProfileId");
        	mProfile = Profile.getProfile(this, id);
			if (mProfile != null && mRequest == ProfileListActivity.REQ_COPY_PROFILE) {
				mProfile.mProfileName = "Copy of " + mProfile.mProfileName;
			}
			break;
       
        default:
        	break;
        }
		
	}
	
	// a helper function for getData
	private void addDataToList(List<Map<String, Object>>list, String title, String info) {
		if (list == null)
			return;
		
		Map<String, Object> map;

		map = new HashMap<String, Object>();
        map.put("title", title);
        map.put("info", info);
        map.put("more", android.R.drawable.ic_menu_more);
        
        list.add(map);

        return;
	}
	
	// get profile data from content provider.
	// if request is ProfileListActivity.REQ_ADD_PROFILE, use profileName to create one;
	// if request is ProfileListActivity.REQ_EDIT_PROFILE, use profileId to retrieve the data;
	// TODO: replace the strings here with resouce ids
	private List<Map<String, Object>> getData() {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		
		if (mProfile != null) {
			String info;

			// list position: 0, profile name
			addDataToList(list, "Profile Name", mProfile.mProfileName);
			
			// list position: 1, volume
			if (mProfile.mVolumeCall == Profile.NOCHANGE) 
				info = "No Change";
			else
				info = "Volume=" + mProfile.mVolumeCall; 
			addDataToList(list, "Volume", info);
			
			// list position: 2, vibrate
			if (mProfile.mVibrate == Profile.ON)
				info = "Vibrate=on";
			else if (mProfile.mVibrate == Profile.OFF)
				info = "Vibrate=off";
			else
				info = "No Change";
			addDataToList(list, "Vibrate", info);
			
			// list position: 3, wireless
			if (IsWirelessNoChange(mProfile))
				info = "No Change";
			else if (IsWirelessFlightMode(mProfile))
				info = "Flight Mode";
			else
			info = "Cell=" + (mProfile.mCell == Profile.ON ?  "on" : "off")
					+ ", Wifi=" + (mProfile.mWifi == Profile.ON ? "on" : "off") 
					+ ", Bluetooth=" + (mProfile.mBluetooth == Profile.ON ? "on" : "off");

			addDataToList(list, "Wireless", info);
			
			// list position: 4, display
			info = "Timeout=" 
					+ (mProfile.mTimeout == 0 ? "Never" : 
						(mProfile.mTimeout == Profile.NOCHANGE ? "No Change" :
						(mProfile.mTimeout < 60 ? (mProfile.mTimeout + " seconds") : 
							((mProfile.mTimeout / 60) + " minutes"))));
			addDataToList(list, "Display", info);
		}
		
        return list;
	}
	
	// save the profile data to database
	private void saveProfile() {

		if (mRequest == ProfileListActivity.REQ_EDIT_PROFILE) {
			// for edit, update the existing record
			Profile.updateProfile(this, mProfile);
		} else {
			// for add or copy, insert the new record
			Profile.insertProfile(this, mProfile);
		}
		
	}
	
	// dialog warning creator
	private Dialog createDialogWarning() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        builder.setMessage(mWarning)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.dismiss();
                }
            });
        
        return builder.create();
	}

	// dialog profile name creator
	private Dialog createDialogProfileName() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        LayoutInflater factory = LayoutInflater.from(this);
        View dialogView = factory.inflate(R.layout.dialog_edit_text, null);
        final EditText editText = (EditText)dialogView.findViewById(R.id.edit_text);
        editText.setText(mProfile.mProfileName);
        
        builder.setTitle(R.string.profile_name)
            .setView(dialogView)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	String name = editText.getText().toString();
                	
                	if (name.length() <= 0) {
                    	// if name is empty, warn user
                		ProfileActivity.this.setWarning(R.string.warning_profile_name_empty);
                		ProfileActivity.this.showDialog(ProfileActivity.DIALOG_WARNING);
                	} else {
            			// save the profile name
                		mProfile.mProfileName = name;
                		updateListAdapter();
                	}

                	dialog.dismiss();
                }
            })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                	dialog.cancel();
                }
            });
        
        return builder.create();	
	}
	
	// dialog volume creator
	private Dialog createDialogVolume() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_volume, null);
        final RadioGroup settings = (RadioGroup)dialogView.findViewById(R.id.radio_group_volume);
        final SeekBar volume = (SeekBar)dialogView.findViewById(R.id.seek_bar_volume);
        if (mProfile.mVolumeCall == Profile.NOCHANGE) {
        	settings.check(R.id.radio_nochange);
        	volume.setProgress(GetCurrentVolume());
            volume.setEnabled(false);
        } else {
        	settings.check(R.id.radio_change);
        	volume.setProgress(mProfile.mVolumeCall);
        	volume.setEnabled(true);
        }
        
        settings.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    		public void onCheckedChanged(RadioGroup group, int checkedId) {
    			if (checkedId == R.id.radio_nochange) {
    				volume.setEnabled(false);
    			} else {
    				volume.setEnabled(true);
    			}
    		}
    	});

        builder.setTitle(R.string.volume)
        .setView(dialogView)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	if (settings.getCheckedRadioButtonId() == R.id.radio_nochange)
            		mProfile.mVolumeCall = Profile.NOCHANGE;
            	else
            		mProfile.mVolumeCall = volume.getProgress();
            	
           		updateListAdapter();
            	dialog.dismiss();
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	dialog.cancel();
            }
        });

        return builder.create();
	}

	// dialog vibrate creator
	private Dialog createDialogVibrate() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_on_off_nochange, null);
        
        final RadioGroup vibrate = (RadioGroup)dialogView.findViewById(R.id.radio_group);
        if (mProfile.mVibrate == Profile.ON)
        	vibrate.check(R.id.radio_on);
        else if (mProfile.mVibrate == Profile.OFF)
        	vibrate.check(R.id.radio_off);
        else
        	vibrate.check(R.id.radio_nochange);

        builder.setTitle(R.string.vibrate)
        .setView(dialogView)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	if (vibrate.getCheckedRadioButtonId() == R.id.radio_on)
            		mProfile.mVibrate = Profile.ON;
            	else if (vibrate.getCheckedRadioButtonId() == R.id.radio_off)
            		mProfile.mVibrate = Profile.OFF;
            	else 
            		mProfile.mVibrate = Profile.NOCHANGE;
            	
           		updateListAdapter();
            	dialog.dismiss();
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	dialog.cancel();
            }
        });

        return builder.create();
	}
	
	// dialog wireless creator
	private Dialog createDialogWireless() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_wireless, null);
        final RadioGroup settings = (RadioGroup)dialogView.findViewById(R.id.radio_group);
        final ToggleButton cell = (ToggleButton)dialogView.findViewById(R.id.toggle_cell);
        final ToggleButton wifi = (ToggleButton)dialogView.findViewById(R.id.toggle_wifi);
        final ToggleButton bluetooth = (ToggleButton)dialogView.findViewById(R.id.toggle_bluetooth);
        
        if (IsWirelessNoChange(mProfile)) {
        	settings.check(R.id.radio_nochange);
        	cell.setChecked(GetCellStatus());
        	wifi.setChecked(GetWifiStatus());
        	bluetooth.setChecked(GetBluetoothStatus());
        	cell.setEnabled(false);
        	wifi.setEnabled(false);
        	bluetooth.setEnabled(false);
        } else if (IsWirelessFlightMode(mProfile)) {
        	settings.check(R.id.radio_flight);
        	cell.setChecked(false);
        	wifi.setChecked(false);
        	bluetooth.setChecked(false);
        	cell.setEnabled(false);
        	wifi.setEnabled(false);
        	bluetooth.setEnabled(false);
        } else {
        	settings.check(R.id.radio_change);
        	cell.setChecked(mProfile.mCell > 0);
        	wifi.setChecked(mProfile.mWifi > 0);
        	bluetooth.setChecked(mProfile.mBluetooth > 0);
        	cell.setEnabled(true);
        	wifi.setEnabled(true);
        	bluetooth.setEnabled(true);
        }
        
        settings.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    		public void onCheckedChanged(RadioGroup group, int checkedId) {
    			if (checkedId == R.id.radio_nochange) {
    	        	cell.setEnabled(false);
    	        	wifi.setEnabled(false);
    	        	bluetooth.setEnabled(false);
    			} else if (checkedId == R.id.radio_flight) {
    	        	cell.setEnabled(false);
    	        	wifi.setEnabled(false);
    	        	bluetooth.setEnabled(false);
    			} else {
    	        	cell.setEnabled(true);
    	        	wifi.setEnabled(true);
    	        	bluetooth.setEnabled(true);
    			}
    		}
    	});
        
        builder.setTitle(R.string.wireless)
        .setView(dialogView)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	if (settings.getCheckedRadioButtonId() == R.id.radio_nochange) {
            		SetWirelessNoChange(mProfile);
            	} else if (settings.getCheckedRadioButtonId() == R.id.radio_flight) {
            		SetWirelessFlightMode(mProfile);
            	} else {
                	mProfile.mCell = cell.isChecked() ? Profile.ON : Profile.OFF;
                	mProfile.mWifi = wifi.isChecked() ? Profile.ON : Profile.OFF;
                	mProfile.mBluetooth = bluetooth.isChecked() ? Profile.ON : Profile.OFF;
            	}
            	
           		updateListAdapter();
            	dialog.dismiss();
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	dialog.cancel();
            }
        });

        return builder.create();
	}

	// dialog display creator
	private Dialog createDialogDisplay() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        
        LayoutInflater factory = LayoutInflater.from(this);
        final View dialogView = factory.inflate(R.layout.dialog_display, null);
        
        final RadioGroup timeout = (RadioGroup)dialogView.findViewById(R.id.radio_group_screen_timeout);
        timeout.check(TimeoutToRadioId(mProfile.mTimeout));

        builder.setTitle(R.string.display)
        .setView(dialogView)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	mProfile.mTimeout = RadioIdToTimeout(timeout.getCheckedRadioButtonId());
            	
           		updateListAdapter();
            	dialog.dismiss();
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            	dialog.cancel();
            }
        });

        return builder.create();
	}

	
	// screen timeout radio button id to timeout value converter
	private int RadioIdToTimeout(int id) {
		int timeout = TIMEOUT_NEVER;
		switch(id) {
		case R.id.radio_nochange:
			timeout = TIMEOUT_NOCHANGE;
			break;
		case R.id.radio_30_seconds:
			timeout = TIMEOUT_30S;
			break;
		case R.id.radio_1_minute:
			timeout = TIMEOUT_1M;
			break;
		case R.id.radio_2_minutes:
			timeout = TIMEOUT_2M;
			break;
		case R.id.radio_5_minutes:
			timeout = TIMEOUT_5M;
			break;
		case R.id.radio_10_minutes:
			timeout = TIMEOUT_10M;
			break;
		case R.id.radio_never:
			timeout = TIMEOUT_NEVER;
			break;
		default:
			timeout = TIMEOUT_30S;
			break;
		}
			
		return timeout;
	}
	
	// screen timeout value to radio button id converter
	private int TimeoutToRadioId(int timeout) {
		int id = R.id.radio_never;
		switch(timeout) {
		case TIMEOUT_NOCHANGE:
			id = R.id.radio_nochange;
			break;
		case TIMEOUT_30S:
			id = R.id.radio_30_seconds;
			break;
		case TIMEOUT_1M:
			id = R.id.radio_1_minute;
			break;
		case TIMEOUT_2M:
			id = R.id.radio_2_minutes;
			break;
		case TIMEOUT_5M:
			id = R.id.radio_5_minutes;
			break;
		case TIMEOUT_10M:
			id = R.id.radio_10_minutes;
			break;
		case TIMEOUT_NEVER:
			id = R.id.radio_never;
			break;
		default:
			id = R.id.radio_30_seconds;
			break;
		}
		
		return id;
	}
	
	private boolean IsWirelessNoChange(Profile p)
	{
		return (p.mCell == Profile.NOCHANGE
				&& p.mWifi == Profile.NOCHANGE
				&& p.mBluetooth == Profile.NOCHANGE);
	}
	
	private boolean IsWirelessFlightMode(Profile p)
	{
		return (p.mCell == Profile.FLIGHT
				&& p.mWifi == Profile.FLIGHT
				&& p.mBluetooth == Profile.FLIGHT);
	}
	
	private void SetWirelessNoChange(Profile p)
	{
		p.mCell = Profile.NOCHANGE;
		p.mWifi = Profile.NOCHANGE;
		p.mBluetooth = Profile.NOCHANGE;
	}
	
	private void SetWirelessFlightMode(Profile p)
	{
		p.mCell = Profile.FLIGHT;
		p.mWifi = Profile.FLIGHT;
		p.mBluetooth = Profile.FLIGHT;
	}
	
	private int GetCurrentVolume() {
		AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
		return am.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
	}
	
	private boolean GetCellStatus() {
		return (Settings.System.getInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0);
	}
	
	private boolean GetWifiStatus() {
		WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
		return (wm.getWifiState() != WifiManager.WIFI_STATE_DISABLED);
	}

	private boolean GetBluetoothStatus() {
		BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
		return (adapter.getState() != BluetoothAdapter.STATE_OFF);
	}

	// Inner classes
		
}
